package de.hwrberlin.remo.diagram.custom.decorators;

import org.eclipse.emf.common.notify.Notification;
import org.eclipse.emf.transaction.TransactionalEditingDomain;
import org.eclipse.gef.EditPart;
import org.eclipse.gmf.runtime.diagram.core.listener.DiagramEventBroker;
import org.eclipse.gmf.runtime.diagram.core.listener.NotificationListener;
import org.eclipse.gmf.runtime.diagram.ui.editparts.GraphicalEditPart;
import org.eclipse.gmf.runtime.diagram.ui.editparts.ShapeEditPart;
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.AbstractDecorator;
import org.eclipse.gmf.runtime.diagram.ui.services.decorator.IDecoratorTarget;
import org.eclipse.gmf.runtime.draw2d.ui.mapmode.MapModeUtil;
import org.eclipse.gmf.runtime.notation.View;
import org.eclipse.swt.graphics.Image;
import de.hwrberlin.remo.diagram.custom.util.ImageUtil;
import de.hwrberlin.remo.diagram.custom.util.Images;
import de.hwrberlin.remo.model.ElementState;
import de.hwrberlin.remo.model.KnowledgeBase;
import de.hwrberlin.remo.model.KnowledgeBaseElement;
import de.hwrberlin.remo.model.RemoModelPackage;
import de.hwrberlin.remo.model.Rule;


public class ElementStateDecorator extends AbstractDecorator implements
		NotificationListener {

	public ElementStateDecorator(IDecoratorTarget decoratorTarget) {
		super(decoratorTarget);	
		removeListeners();
		addListeners();
	}

	@Override
	public void activate() {
		refresh();
	}

	public void refresh() {
		Image image = null;
		removeDecoration();
		
		EditPart editPart = (EditPart) getDecoratorTarget().getAdapter(
				EditPart.class);
		
		View view = (View) getDecoratorTarget().getAdapter(View.class);
		KnowledgeBaseElement element = (KnowledgeBaseElement) view.getElement();
		if (element.getState() == ElementState.TRUE) {
			image = ImageUtil.getImage(Images.TRUE_IMAGE);
			
		} else if(element.getState() ==  ElementState.FALSE) {
			image = ImageUtil.getImage(Images.FALSE_IMAGE);

		} 
		else if(element.getState() == ElementState.UNKNOWN) {
			if(element instanceof Rule) {
				if(((Rule)element).isValidated()) {
					image = ImageUtil.getImage(Images.UNKNOWN_IMAGE);
				}
			} else {
				image = ImageUtil.getImage(Images.UNKNOWN_IMAGE);
			}
		} 
		
		if(image != null) {
			setDecoration(getDecoratorTarget().addShapeDecoration(
						  image, 
						  IDecoratorTarget.Direction.NORTH_EAST,
						  MapModeUtil.getMapMode(((ShapeEditPart) editPart).getFigure()).DPtoLP(-1), false));
		} else {
			removeDecoration();
		}
	}
	
	@Override
	public void notifyChanged(Notification notification) {
		Object feature = notification.getFeature();
		
		if (RemoModelPackage.Literals.KNOWLEDGE_BASE_ELEMENT__STATE.equals(feature)) {
			refresh();
		} else if(RemoModelPackage.Literals.RULE__VALIDATED.equals(feature)) {
			refresh();
		}
//		else if (RemoModelPackage.Literals.KNOWLEDGE_BASE_ELEMENT__STATE.equals(feature)) {
//			Object obj1 = notification.getOldValue();
//			Object obj2 = ((GraphicalEditPart)getDecoratorTarget().getAdapter(GraphicalEditPart.class)).resolveSemanticElement();
//			if (obj1 == obj2) {
//				removeDecoration();
//				removeListeners();
//			}
//		}
	}

	private void addListeners() {
		GraphicalEditPart editPart = (GraphicalEditPart) getDecoratorTarget().getAdapter(GraphicalEditPart.class);

		if (editPart != null) {
			KnowledgeBaseElement kbElement = (KnowledgeBaseElement) editPart.resolveSemanticElement();
			if (kbElement == null || kbElement.eIsProxy()) {
				return;
			}
			TransactionalEditingDomain theEditingDomain = editPart.getEditingDomain();
			
			if (theEditingDomain != null) {
				DiagramEventBroker diagramEventBroker = DiagramEventBroker.getInstance(theEditingDomain);
				KnowledgeBase base = (KnowledgeBase) kbElement.eContainer();
				
				diagramEventBroker.addNotificationListener(kbElement, this);
				diagramEventBroker.addNotificationListener(base, this);
			}
		}
	}
	
	private void removeListeners() {
		GraphicalEditPart editPart = (GraphicalEditPart) getDecoratorTarget()
				.getAdapter(GraphicalEditPart.class);
		
		if (editPart != null) {
			KnowledgeBaseElement kbElement = (KnowledgeBaseElement) editPart.resolveSemanticElement();
			if (kbElement == null || kbElement.eIsProxy()) {
				return;
			}
			TransactionalEditingDomain theEditingDomain = editPart.getEditingDomain();
			
			if (theEditingDomain != null) {
				DiagramEventBroker diagramEventBroker = DiagramEventBroker.getInstance(theEditingDomain);
				KnowledgeBase base = (KnowledgeBase) kbElement.eContainer();
				
				diagramEventBroker.removeNotificationListener(kbElement, this);
				diagramEventBroker.removeNotificationListener(base, this);
			}
		}
	}
}
